iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0
自我挑戰組

跟著 Go 實戰聖經 一起自學 Go系列 第 28

DAY 28 Go 語言 函式 (function) 用 defer 延後執行函式

  • 分享至 

  • xImage
  •  

用 defer 延後執行函式

defer 中文是推遲的意思,而在函式裡執行 defer 顧名思義就是延遲函式執行的時間,當使用 defer 的函式可以等到父函式結束前一刻才會執行。

範例 1:

package main

import "fmt"

func main() {
    fmt.Println("在 defer 函式前印出的字")
    defer deferFunc() // 在函式前加入 defer 便會在 main() 函式最後才會執行
    fmt.Println("在 defer 函式後印出的字")
}

func deferFunc() {
    fmt.Println("我是 defer 函式")
}

範例 1(執行結果):

在 defer 函式前印出的字
在 defer 函式後印出的字
我是 defer 函式

defer 同時也可以使用在匿名函式中:

範例 2:

package main

import "fmt"

func main() {
    fmt.Println("在匿名函式前印出的字")
    defer func() {
        fmt.Println("我是匿名的 defer 函式")
    }() // 在匿名函式前加 defer
    fmt.Println("在匿名函式後印出的字")
}

範例 2(執行結果):

在匿名函式前印出的字
在匿名函式後印出的字
我是匿名的 defer 函式

通常我們使用 defer 大部分是,釋出資源關閉開啟檔案移除程式清空值,或是也可以將它拿來當處理錯誤的狀況。

多重 defer 的執行函式

這時調皮的我想說那我一次呼叫很多 defer 函式會發生什麼事呢?
範例 3:

package main

import "fmt"

func main() {
    fmt.Println("在 defer 函式前印出的字")
    defer defer1() // 接收傳回的 addFunc 函式
    fmt.Println("在 defer 函式後印出的字")
    defer defer2()

    defer defer3()

    defer defer4()
    func() {
        fmt.Println("我是 main() 裡的匿名函式")
    }()
}

func defer1() {
    fmt.Println("我是 defer 函式 1")
}

func defer2() {
    fmt.Println("我是 defer 函式 2")
}

func defer3() {
    fmt.Println("我是 defer 函式 3")
}

func defer4() {
    fmt.Println("我是 defer 函式 4")
}

範例 3(執行結果):

在 defer 函式前印出的字
在 defer 函式後印出的字
我是 main() 裡的匿名函式
我是 defer 函式 4
我是 defer 函式 3
我是 defer 函式 2
我是 defer 函式 1

通過範例我們可以得知若是很多個 defer 會是先進後出的方式呈現,若是比較抽象可以根據下圖來想像,我們將 defer 函式 1~4 一一放進左方的容器,拿出時會從 4 開始拿起。

多個 defer 函式示意圖

defer 對變數值的副作用

即使 defer 函式會在父函式的最後才執行,但當 defer 函式有使用到外部變數時,他還是會先取得當下的變數值,然後在最後才執行,也就是說若是在呼叫 defer 值後,又更改變數值,並不會影響先前呼叫 defer 函式的值。
範例 4:

package main

import "fmt"

func main() {
    name := "奇犽"
    age := 12
    defer myFavorite(name, age)

    name = "西索"
    age = 26
    myFavorite(name, age)
}

func myFavorite(name string, age int) {
    fmt.Println("我最喜歡的人是:", name, " 他", age, "歲")
}

範例 4(執行結果):

我最喜歡的人是: 西索  他 26 歲
我最喜歡的人是: 奇犽  他 12 歲

根據範例 4 我們得知,雖然 defer 晚執行,但他拿到的變數值依然是原本的 奇犽

終於介紹完所有函式 (function),相信大家對於函式有一定的了解了,那我們明天繼續學習在 Go 語言中也不可或缺的 錯誤處理 ,明天見~~


上一篇
DAY 27 Go 語言 函式 (function) 匿名函式與閉包
下一篇
DAY 29 Go 語言 程式錯誤的類型
系列文
跟著 Go 實戰聖經 一起自學 Go30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言